/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ru.example.netcracker.player;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;
import javazoom.jl.player.advanced.AdvancedPlayer;
import javazoom.jl.player.advanced.PlaybackEvent;
import javazoom.jl.player.advanced.PlaybackListener;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

/**
 *
 * @author Nikolay
 */
public class Player implements Runnable, PlayerFacade {
    
    private static final Logger LOG = Logger.getLogger(Player.class.getName());  
    
    private AdvancedPlayer player;
    private File alarm;
    private Thread playerThread = null;
    
    private class Playback extends PlaybackListener {

        @Override
        public void playbackFinished(PlaybackEvent pe) {
            super.playbackFinished(pe);
            //System.out.println("playbackFinished " + pe.toString());
        }

        @Override
        public void playbackStarted(PlaybackEvent pe) {
            super.playbackStarted(pe);
            //System.out.println("playbackStarted " + pe.toString());
        }
        
    }
    
    public Player() {
    }
    
    public Player(File alarm) {
        this.alarm = alarm;
    }
    
    @Override
    public File getAlarmFile() {
        return alarm;
    }

    @Override
    public void setAlarmFile(File alarm) {
        LOG.log(Level.INFO, "alarm file path: " + alarm.getAbsolutePath());
        this.alarm = alarm;
    }

    private AudioDevice getAudioDevice() throws JavaLayerException {
        return FactoryRegistry.systemRegistry().createAudioDevice();
    }

    private void stop() throws JavaLayerException {
        LOG.log(Level.INFO, "stop player");
        if (player != null) {
            player.close();
            player = null;
            playerThread = null;
        }
    }

    private void play(InputStream in, AudioDevice dev) throws JavaLayerException {
        LOG.log(Level.INFO, "start player");
        stop();

        if (in != null && dev != null) {
            player = new AdvancedPlayer(in, dev);
            player.setPlayBackListener(new Playback());
            playerThread = createPlayerThread();
            playerThread.start();
        }
    }

    private Thread createPlayerThread() {
        LOG.log(Level.INFO, "create new player thread");
        return new Thread(this, "Audio player thread");
    }
    
    @Override
    public void startPlayer(String path) {
        setAlarmFile(new File(path));
        startPlayer();
    }
    
    @Override
    public void startPlayer(File alarm) {
        setAlarmFile(alarm);
        startPlayer();
    }
    
    @Override
    public void startPlayer() {
        try {
            InputStream in = new FileInputStream(alarm);
            AudioDevice dev = getAudioDevice();
            play(in, dev);
        } catch (JavaLayerException | FileNotFoundException ex) {
            LOG.log(Level.ERROR, "Exception: ", ex);
        }
    }
    
    @Override
    public void stopPlayer() {
        try {
            stop();
        } catch (JavaLayerException ex) {
            LOG.log(Level.ERROR, "Exception: ", ex);
        }
    }
    
    @Override
    public void run() {
        if (player != null) {
            try {
                player.play();
            } catch (JavaLayerException ex) {
                LOG.log(Level.ERROR, "Exception: ", ex);
            }
        }
    }
}
